package it.nexsoft.dyn.compiler;

import it.nexsoft.dyn.DynException;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;

class DynClassLoader extends ClassLoader {

	private ClassLoader parent = null;
	private DynClassRepos repos = null;
	
	public DynClassLoader(DynClassRepos repos, ClassLoader parent) {
		this.parent = parent;
		this.repos = repos;
	}
	
	public Class<?> defineClassFromBytes(String name, byte[] javaByteCode) {
		return defineClass(name, javaByteCode, 0, javaByteCode.length);
	}
	
	@Override
	public InputStream getResourceAsStream(String name) {
		return parent.getResourceAsStream(name);
	}
	
	@Override
	public URL getResource(String name) {
		return parent.getResource(name);
	}
	
	@Override
	public Enumeration<URL> getResources(String name) throws IOException {
		return parent.getResources(name);
	}
	
	@Override
	public synchronized void setClassAssertionStatus(String className, boolean enabled) {
		parent.setClassAssertionStatus(className, enabled);
	}
	
	@Override
	public synchronized void setPackageAssertionStatus(String packageName, boolean enabled) {
		parent.setPackageAssertionStatus(packageName, enabled);
	}
	
	@Override
	public Class<?> loadClass(String name) throws ClassNotFoundException {
		DynClass cl = repos.get(name);
		if (cl == null)
			return parent.loadClass(name);
		
		return cl.getClass();
	}

	
	
	@Override
	public synchronized void setDefaultAssertionStatus(boolean enabled) {
		parent.setDefaultAssertionStatus(enabled);
	}
	
	/**
     * get the byte code of the given class.
     */
    public byte[] getClassDefinition(String name) {
        name = name.replace(".", "/") + ".class";
        InputStream is = getResourceAsStream(name);
        if (is == null) {
            return null;
        }
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            byte[] buffer = new byte[8192];
            int count;
            while ((count = is.read(buffer, 0, buffer.length)) > 0) {
                os.write(buffer, 0, count);
            }
            return os.toByteArray();
        } catch (Exception e) {
            throw new DynException(e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                throw new DynException(e);
            }
        }
    }
}
